﻿namespace EasyWeb.Test
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Linq;
    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using EasyWeb.Configuration;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class EWConfigurationDao_Test : LibraryTest
    {
        #region Default language

        [TestMethod]
        public async Task Select_DefaultLanguage_Test()
        {
            var raw = await this.TestDbContext.ew_tbl_configurations.FindAsync(EWCommon.ConfigurationIdDefaultLanguage);
            var values = EWModelHelpers.Configuration.DefaultLanguage.ParseXml(raw.ew_xml_value_1);

            var actual = await this.ConfigurationDao.SelectAsync<EWDefaultLanguageConfiguration>();

            Assert.AreEqual(raw.ew_uid_configuration_id, actual.Id);
            CollectionAssert.AreEqual(raw.ew_t_timestamp, actual.Timestamp);
            Assert.AreEqual(values.Item1, actual.DefaultLanguage);
            Assert.AreEqual(values.Item2, actual.UseBrowserSetting);
            Assert.AreEqual(values.Item3, actual.UseDefault);
        }

        [TestMethod]
        public async Task Update_DefaultLanguage_Test()
        {
            var original = await this.TestDbContext.ew_tbl_configurations.FindAsync(EWCommon.ConfigurationIdDefaultLanguage);
            this.TestDbContext.Entry(original).State = EntityState.Detached;
            var values = EWModelHelpers.Configuration.DefaultLanguage.ParseXml(original.ew_xml_value_1);

            var updating = new EWDefaultLanguageConfiguration()
            {
                Id = original.ew_uid_configuration_id,
                Timestamp = original.ew_t_timestamp,
                DefaultLanguage = Exchange(values.Item1, "en", "zh-Hans"),
                UseBrowserSetting = !values.Item2,
                UseDefault = !values.Item3,
            };
            await this.ConfigurationDao.UpdateAsync(updating);

            var updated = await this.ConfigurationDao.SelectAsync<EWDefaultLanguageConfiguration>();

            Assert.AreEqual(updating.Id, updated.Id);
            CollectionAssert.AreEqual(updating.Timestamp, updated.Timestamp);
            Assert.AreEqual(updating.DefaultLanguage, updated.DefaultLanguage);
            Assert.AreEqual(updating.UseBrowserSetting, updated.UseBrowserSetting);
            Assert.AreEqual(updating.UseDefault, updated.UseDefault);

            foreach (var update in new[] { updating, updated })
            {
                Assert.AreEqual(original.ew_uid_configuration_id, update.Id);
                CollectionAssert.AreNotEqual(original.ew_t_timestamp, update.Timestamp);
                Assert.AreEqual(Exchange(values.Item1, "en", "zh-Hans"), update.DefaultLanguage);
                Assert.AreNotEqual(values.Item2, update.UseBrowserSetting);
                Assert.AreNotEqual(values.Item3, update.UseDefault);
            }

            var current = await this.TestDbContext.ew_tbl_configurations.FindAsync(EWCommon.ConfigurationIdDefaultLanguage);
            await this.TestDbContext.Entry(current).ReloadAsync();
            values = EWModelHelpers.Configuration.DefaultLanguage.ParseXml(current.ew_xml_value_1);
            Assert.AreEqual(current.ew_uid_configuration_id, updated.Id);
            CollectionAssert.AreEqual(current.ew_t_timestamp, updated.Timestamp);
            Assert.AreEqual(values.Item1, updated.DefaultLanguage);
            Assert.AreEqual(values.Item2, updated.UseBrowserSetting);
            Assert.AreEqual(values.Item3, updated.UseDefault);

            Assert.AreEqual(original.ew_dt_created, current.ew_dt_created);
            Assert.AreEqual(original.ew_nvc_created_by, current.ew_nvc_created_by);
            Assert.AreNotEqual(original.ew_dt_modified, current.ew_dt_modified);
            Assert.AreNotEqual(original.ew_nvc_modified_by, current.ew_nvc_modified_by);
        }

        #endregion

        #region System prefix

        [TestMethod]
        public async Task Select_SystemPrefix_Test()
        {
            var raw = await this.TestDbContext.ew_tbl_configurations.FindAsync(EWCommon.ConfigurationIdSystemPrefix);
            var values = EWModelHelpers.Configuration.SystemPrefix.ParseXml(raw.ew_xml_value_1);

            var actual = await this.ConfigurationDao.SelectAsync<EWSystemPrefixConfiguration>();

            Assert.AreEqual(raw.ew_uid_configuration_id, actual.Id);
            CollectionAssert.AreEqual(raw.ew_t_timestamp, actual.Timestamp);
            Assert.AreEqual(values.Item1, actual.Value);
        }

        [TestMethod]
        public async Task Update_SystemPrefix_Test()
        {
            var original = await this.TestDbContext.ew_tbl_configurations.FindAsync(EWCommon.ConfigurationIdSystemPrefix);
            this.TestDbContext.Entry(original).State = EntityState.Detached;
            var values = EWModelHelpers.Configuration.SystemPrefix.ParseXml(original.ew_xml_value_1);

            var updating = new EWSystemPrefixConfiguration()
            {
                Id = original.ew_uid_configuration_id,
                Timestamp = original.ew_t_timestamp,
                Value = "test",
            };
            await this.ConfigurationDao.UpdateAsync(updating);

            var updated = await this.ConfigurationDao.SelectAsync<EWSystemPrefixConfiguration>();

            Assert.AreEqual(updating.Id, updated.Id);
            CollectionAssert.AreEqual(updating.Timestamp, updated.Timestamp);
            Assert.AreEqual(updating.Value, updated.Value);

            foreach (var update in new[] { updating, updated })
            {
                Assert.AreEqual(original.ew_uid_configuration_id, update.Id);
                CollectionAssert.AreNotEqual(original.ew_t_timestamp, update.Timestamp);
                Assert.AreNotEqual(values.Item1, update.Value);
            }

            var current = await this.TestDbContext.ew_tbl_configurations.FindAsync(EWCommon.ConfigurationIdSystemPrefix);
            await this.TestDbContext.Entry(current).ReloadAsync();
            values = EWModelHelpers.Configuration.SystemPrefix.ParseXml(current.ew_xml_value_1);
            Assert.AreEqual(current.ew_uid_configuration_id, updated.Id);
            CollectionAssert.AreEqual(current.ew_t_timestamp, updated.Timestamp);
            Assert.AreEqual(values.Item1, updated.Value);

            Assert.AreEqual(original.ew_dt_created, current.ew_dt_created);
            Assert.AreEqual(original.ew_nvc_created_by, current.ew_nvc_created_by);
            Assert.AreNotEqual(original.ew_dt_modified, current.ew_dt_modified);
            Assert.AreNotEqual(original.ew_nvc_modified_by, current.ew_nvc_modified_by);
        }

        #endregion

        #region Create

        [TestMethod]
        [ExpectedException(typeof(NotSupportedException))]
        public void Create_Test()
        {
            this.ConfigurationDao.CreateAsync(new EWDefaultLanguageConfiguration());
        }

        #endregion

        #region Delete

        [TestMethod]
        [ExpectedException(typeof(NotSupportedException))]
        public void Delete_Test()
        {
            this.ConfigurationDao.DeleteAsync(Guid.NewGuid(), new byte[] { });
        }

        #endregion

        #region Helpers

        private static T Exchange<T>(T source, T comparand, T value)
        {
            return object.Equals(source, comparand) ? value : comparand;
        }

        #endregion
    }
}
